Skip to main content

Usare l'interfaccia di scripting Git

CODESYS Git fornisce un'interfaccia di scripting per Git. Di seguito sono riportati alcuni esempi di come utilizzare l'interfaccia. Di seguito troverai anche informazioni sull'output testuale dei messaggi generati da molte operazioni Git

Per ulteriori informazioni, vedere: Documentazione dell'API del motore di script

Requisiti

Per eseguire gli esempi seguenti, è necessario quanto segue:

  • CODESYS 3.5.19.30 o versioni successive

Sono inoltre necessari i seguenti componenti:

  • CODESYS Library Documentation Support (per creare la libreria compilata)

  • CODESYS Git 1.6.0.0 o versioni successive

  • Un'installazione Git locale

Importante

Usa le password SecureString quando possibile

Per una maggiore sicurezza, le password devono essere passate come .NET SecureString.

Le operazioni GIT interessate sono: clone, fetch, pull, push

SecureStrings possono essere create in IronPython come segue. La «password» stessa deve provenire da una stringa sicura e non, come qui a scopo dimostrativo, essere in testo semplice nello script. Internamente, ogni password fornita viene gestita in modo sicuro

        from System.Security import SecureString 

        sec_str_password = SecureString()
        for c in "Passwort":    
            sec_str_password.AppendChar(c)

Per ulteriori misure di sicurezza durante l'utilizzo CODESYS Git vedi: Sicurezza per CODESYS Git

Preparazione

CODESYS biblioteca

Perché no CODESYS le librerie sono attualmente gestite in Git, i sorgenti di a CODESYS le librerie sono obbligatorie. String Functions.library libreria da CODESYS String Libraries il prodotto viene utilizzato negli esempi.

Repository Git remoto

Per questo esempio, un repository Git nudo nel file system viene utilizzato come repository remoto.

Per prepararti, elimina prima la cartella corrispondente e poi creane una nuova.

import shutil
import os 

def prepare_empty_dir(empty_dir_path):
    print("Prepare empty directory at", empty_dir_path)
    shutil.rmtree(empty_dir_path, ignore_errors=True)
    if not(os.path.exists(empty_dir_path) and os.path.isdir(empty_dir_path)):
        os.makedirs(empty_dir_path)

Viene quindi creato un repository Git vuoto.

import subprocess
def create_bare_git_repository(bare_repository_path):
    print("Create bare git repository at", bare_repository_path)
    create_bare_repository_cmd = 'cmd /c "git -C \"' + bare_repository_path + '\" init --bare"'
    try:
        retcode = subprocess.call(create_bare_repository_cmd, shell=True)
        if retcode < 0:
            raise Exception("Creating bare git repository at " + bare_repository_path + " failed: ", -retcode)
        else:
            print("Creating bare git repository at " + bare_repository_path + " succeeded.")
    except Exception as e:
        print("[ERROR] Creating bare git repository failed: ", e)
        raise

Il repository Git vuoto e nudo è riempito con il contenuto di CODESYS libreria.

def initialize_bare_git_repository(library_path, local_repository_path, bare_repository_path):
    print("Open library:", library_path)
    project = projects.open(library_path)
     
    print("Initiate local git repository")
    project.git.init(local_repository_path)
    project.git.commit_complete("Create git repo for lib", "user", "mail@mail")
     
    print("Push to remote git repository")
    origin_remote = project.git.remote_add("origin", bare_repository_path)
    project.git.branch_set_upstream_to(origin_remote)
    project.git.push()
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

Lo script seguente esegue le funzioni descritte.

import os

def main():
    if projects.primary:
        projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1.library"
    library_path = os.path.join(project_basepath, library_file_name)

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Create and push library to remote git repository")
    
    prepare_empty_dir(remote_repo_path)
    create_bare_git_repository(remote_repo_path)
    initialize_bare_git_repository(library_path, local_repo_path, remote_repo_path)

    print("[Success] All done")


if __name__ == '__main__':
    main()

Il semplice repository Git creato in questo modo e dotato di contenuti viene utilizzato per gli altri esempi.

Clonazione di un repository Git remoto

La seguente funzione viene eseguita git clone per un repository Git remoto.

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode    
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

Creazione e fusione di una nuova filiale

La seguente funzione ausiliaria crea alcuni nuovi oggetti in un CODESYS progetto come esempio.

def add_dut(project):
    ST_STRUCT_STR = """\
        a : BOOL;
        b : BIT;
        c : BIT;
    """

    ST_UNION_STR = """\
    TYPE ExampleUnion :
    UNION
        Zahl : INT;
        Prozent : ExampleAlias;
        Bits : ExampleStruct;
    END_UNION
    END_TYPE
    """

   # Create a struct DUT and insert the list of variables just into the right
   # place in line two, row 0 (line numbering starts with line 0)
   example_dut_struct = project.create_dut('ExampleStruct') # DutType.Structure is the default
   example_dut_struct.textual_declaration.insert(2, 0, ST_STRUCT_STR) 

   # Alias types get their "content" via the base type, which will just end up 
   # as one line in the declaration part:    
   # TYPE MyAlias : INT (0..100); END_TYPE 
   example_dut_alias = project.create_dut('ExampleAlias', DutType.Alias, "INT (0..100)") 

   # Instead of injecting the variables into the existing declaration, 
   # one can also just replace the complete declaration part, including the 
   # boilerplate code.
   example_dut_union = project.create_dut('ExampleUnion', DutType.Union)
   example_dut_union.textual_declaration.replace(ST_UNION_STR)

La seguente funzione ausiliaria incrementa la versione di build nelle informazioni di progetto di un CODESYS progetto.

def increment_build_version(project):
    """
    Increment build version in project info.
    """
    info = project.get_project_info()
    old_version = info.version
    info.version = (old_version.Major, old_version.Minor, old_version.Build + 1, 0)
    project.save()

La seguente funzione crea prima un nuovo ramo e apporta modifiche a questo ramo, quindi unisce nuovamente queste modifiche nel ramo principale.

def copy_branch_and_merge(project):
    current_branch = project.git.branch_show_current()
    print("Current branch: ", current_branch.friendly_name)
    project, current_branch = project.git.branch_copy(current_branch, "new_branch", checkout=True)
    print("Current branch: ", current_branch.friendly_name)

    add_dut(project)
    project.git.commit_complete("Added DUT", "user", "mail@mail")

    increment_build_version(project)
    project.git.commit_complete("Incremented build version", "user", "mail@mail")

    project, current_branch = project.git.checkout("master")
    print("Current branch: ", current_branch.friendly_name)
    project, merge_result = project.git.merge("new_branch")
    print("Merged: ", merge_result.ToString())
    project.save()
    return project

Il seguente script viene eseguito git clone per un repository Git remoto, apporta modifiche al progetto e quindi invia le modifiche al repository Git remoto (CopyBranchAndMerge.py).

def main():
    if projects.primary: 
       projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)
    project = copy_branch_and_merge(project)
    project.git.push()
    project.save()
    project.git.de_init(cleanUpFileSystem=True)
    project.save()
    project.close()
    print("[Success] All done")

if __name__ == '__main__':
    main())

Creazione di una libreria compilata

Il seguente script viene eseguito git clone per un CODESYS libreria sorgente da un repository Git remoto e quindi crea una libreria compilata da esso (CreateCompiledLibrary.py).

import os

class CompileError(Exception):
    pass

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def create_compiled_library(project):
    # requires the CODESYS Library Documentation Support Package!
    project.check_all_pool_objects()
    compile_result_message = system.get_messages(category='{97F48D64-A2A3-4856-B640-75C046E37EA9}')[-1]
    if "0 errors" in compile_result_message:
        project.save_as_compiled_library(destination_name=None)
    else:
        raise CompileError("Compile failed: " + compile_result_message)
    return project

basepath = "D:\\JiraTickets\\GIT-145\\"

project_basepath = os.path.join(basepath, "projects\\")

remote_repo_basepath = os.path.join(basepath, "remotes\\")
remote_repo_directory_name = "StringFunctions.git"
remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

local_repo_basepath = os.path.join(basepath, "repos\\")
local_repo_path = os.path.join(local_repo_basepath, "StringFunctions.git")

print("Clone project")
project = clone_git_repository(project_basepath, "String Functions Cloned.library", remote_repo_path, local_repo_path)
project = create_compiled_library(project)
project.git.de_init(cleanUpFileSystem=True)
project.close()

print("[Success] All done")

Installazione di una libreria da un repository Git remoto

Il seguente script viene eseguito git clone per un CODESYS libreria sorgente da un repository Git remoto e installa questa libreria nella versione corrente CODESYS istanza (InstallLibrary.py).

import os

def clone_git_repository(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def install_library(project):
    library_repo = librarymanager.repositories[0]
    librarymanager.install_library(project.path, library_repo, True)

def main():
    if projects.primary:
        projects.primary.close()

     basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned2.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)

    print("Install library")
    install_library(project)
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

    print("[Success] All done")

if __name__ == '__main__':
    main()

Output di messaggi per operazioni Git

Quando si utilizza CODESYS Git, la maggior parte dei comandi fornisce un output basato su testo. Durante l'esecuzione CODESYS nella riga di comando, viene emesso automaticamente durante l'esecuzione di CODESYS Git comandi tramite il driver di script. Quando si utilizza CODESYS Git nel CODESYS Development System, le uscite vengono visualizzate anche nella finestra dei messaggi.

Structure of the messages: Git:<severity>: [<time>] <text>

In the user interface of CODESYS Git, the output is reduced to: [<time>] <text>

  • severity: categoria di messaggi. Le categorie vanno da quelle puramente informative a quelle relative agli errori critici

  • time: ora esatta del messaggio. Formato: HH:MM:SS

  • text: Contenuto del messaggio. Per i comandi Git standard, il contenuto corrisponde al comando della riga di comando che fornirebbe lo stesso risultato della chiamata effettuata al driver di script. CODESYS Git comandi che non corrispondono a un comando Git standard (ad esempio, Recupera il progetto dal repository), il testo del messaggio spiega l'azione eseguita.

Commands with multiple messages:

Per alcuni comandi (ad esempio, git log), l'output è suddiviso in più messaggi. Nel caso di git log, ogni commit visualizzato viene mostrato in un messaggio separato. In questo caso, per chiarire che questi messaggi fanno parte del git log comando, viene fatto riferimento al comando originale nei messaggi.